<template>
  <a-menu
    :mode="topMenu ? 'horizontal' : 'vertical'"
    v-model:collapsed="collapsed"
    v-model:open-keys="openKeys"
    :show-collapse-button="appStore.device !== 'mobile'"
    :auto-open="false"
    :selected-keys="selectedKey"
    :auto-open-selected="true"
    :level-indent="18"
    style="height: 100%; width: 100%"
    @collapse="setCollapse"
  >
    <template v-for="route in menuTree" :key="route.name">
      <a-sub-menu
        v-if="route.children && route.children.length > 0"
        :key="route.name"
      >
        <template #icon>
          <component v-if="route.meta?.icon" :is="route.meta.icon" />
        </template>
        <template #title>{{ t(route.meta?.locale || '') }}</template>
        <template v-for="child in route.children" :key="child.name">
          <a-sub-menu v-if="child.children && child.children.length > 0" :key="child.name">
            <template #icon>
              <component v-if="child.meta?.icon" :is="child.meta.icon" />
            </template>
            <template #title>{{ t(child.meta?.locale || '') }}</template>
            <a-menu-item
              v-for="grandChild in child.children"
              :key="grandChild.name"
              @click="goto(grandChild)"
            >
              <template #icon>
                <component v-if="grandChild.meta?.icon" :is="grandChild.meta.icon" />
              </template>
              {{ t(grandChild.meta?.locale || '') }}
            </a-menu-item>
          </a-sub-menu>
          <a-menu-item v-else :key="child.name" @click="goto(child)">
            <template #icon>
              <component v-if="child.meta?.icon" :is="child.meta.icon" />
            </template>
            {{ t(child.meta?.locale || '') }}
          </a-menu-item>
        </template>
      </a-sub-menu>
      <a-menu-item v-else :key="route.name" @click="goto(route)">
        <template #icon>
          <component v-if="route.meta?.icon" :is="route.meta.icon" />
        </template>
        {{ t(route.meta?.locale || '') }}
      </a-menu-item>
    </template>
  </a-menu>
</template>

<script lang="ts" setup>
import { useAppStore } from '@/store';
import { openWindow, regexUrl } from '@/utils';
import { listenerRouteChange } from '@/utils/route-listener';
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import type { RouteMeta } from 'vue-router';
import { RouteRecordRaw, useRoute, useRouter } from 'vue-router';
import useMenuTree from './use-menu-tree';

defineEmits(['collapse']);

const { t } = useI18n();
const appStore = useAppStore();
const router = useRouter();
const route = useRoute();
const { menuTree } = useMenuTree();

const collapsed = computed({
  get() {
    if (appStore.device === 'desktop') return appStore.menuCollapse;
    return false;
  },
  set(value: boolean) {
    appStore.updateSettings({ menuCollapse: value });
  },
});

const topMenu = computed(() => appStore.topMenu);
const openKeys = ref<string[]>([]);
const selectedKey = ref<string[]>([]);

const goto = (item: RouteRecordRaw) => {
  // Open external link
  if (regexUrl.test(item.path)) {
    openWindow(item.path);
    selectedKey.value = [item.name as string];
    return;
  }
  // Eliminate external link side effects
  const { hideInMenu, activeMenu } = item.meta as RouteMeta;
  if (route.name === item.name && !hideInMenu && !activeMenu) {
    selectedKey.value = [item.name as string];
    return;
  }
  // Trigger router change
  router.push({
    name: item.name,
  });
};

const findMenuOpenKeys = (target: string) => {
  const result: string[] = [];
  let isFind = false;
  const backtrack = (item: RouteRecordRaw, keys: string[]) => {
    if (item.name === target) {
      isFind = true;
      result.push(...keys);
      return;
    }
    if (item.children?.length) {
      item.children.forEach((el) => {
        backtrack(el, [...keys, el.name as string]);
      });
    }
  };
  menuTree.value.forEach((el: RouteRecordRaw) => {
    if (isFind) return; // Performance optimization
    backtrack(el, [el.name as string]);
  });
  return result;
};

listenerRouteChange((newRoute) => {
  const { requiresAuth, activeMenu, hideInMenu } = newRoute.meta;
  if (requiresAuth && (!hideInMenu || activeMenu)) {
    const menuOpenKeys = findMenuOpenKeys(
      (activeMenu || newRoute.name) as string
    );

    const keySet = new Set([...menuOpenKeys, ...openKeys.value]);
    openKeys.value = [...keySet];

    selectedKey.value = [
      activeMenu || menuOpenKeys[menuOpenKeys.length - 1],
    ];
  }
}, true);

const setCollapse = (val: boolean) => {
  if (appStore.device === 'desktop')
    appStore.updateSettings({ menuCollapse: val });
};
</script>

<style lang="less" scoped>
 :deep(.arco-menu-inner) {
    .arco-menu-inline-header {
      display: flex;
      align-items: center;
    }
    .arco-icon {
      &:not(.arco-icon-down) {
        font-size: 18px;
      }
    }
  }
</style>